package de.servicezombie.tests.spring;

import java.util.LinkedList;
import java.util.List;

import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.core.io.Resource;

import de.servicezombie.cxf.WebserviceTemplateFactory;
import de.servicezombie.cxf.WebserviceTemplateProvider;

public class TcmdbSpringTemplateFactory {

	private static final Logger log = LoggerFactory.getLogger(TcmdbSpringTemplateFactory.class);

	public static final String DEFAULT_PROPERTIES_LOCATION = "file:src/test/resources/tcmdb-config-test.properties";

	private final DefaultResourceLoader resourceLoader = new DefaultResourceLoader();

	public TcmdbSpringTemplateFactory() {
		System.setProperty("de.servicezombie.tcmdb.configuration", DEFAULT_PROPERTIES_LOCATION);
	}

	private SpringTemplate buildByResourceLocation(String... applicationContextLocator) {
		ApplicationContext ac = newApplicatinContext(applicationContextLocator);
		return new SpringTemplate(ac);
	}

	final String[] toXmlFileNames(String prefix, String... names) {

		if (log.isDebugEnabled()) {
			log.debug("toFileNames: >> " + prefix + ", " + ArrayUtils.toString(names));
		}

		List<String> existingXmlFiles = new LinkedList<String>();

		for (String name : names) {

			String filenameProduction = resolvePrefix(prefix, "main") + name + ".xml";
			addResourceIfExists(existingXmlFiles, filenameProduction, true);

			String filenameTest = resolvePrefix(prefix, "test") + name + "-test.xml";
			addResourceIfExists(existingXmlFiles, filenameTest, false);

		}

		String[] result = new String[existingXmlFiles.size()];
		result = existingXmlFiles.toArray(result);

		if (log.isDebugEnabled()) {
			log.debug("toFileNames: << " + ArrayUtils.toString(result));
		}
		return result;
	}

	private String resolvePrefix(String prefix, String type) {
		if (prefix == null) {
			return StringUtils.EMPTY;
		}

		String result = prefix.replace("{type}", type);
		return result;
	}

	private final void addResourceIfExists(List<String> existingXmlFiles, String filenameProduction,
			boolean throwExceptionIfNotExist) {
		Resource resourceProduction = resourceLoader.getResource(filenameProduction);
		if (resourceProduction.exists()) {
			existingXmlFiles.add(filenameProduction);
		}
		else {
			if (throwExceptionIfNotExist) {
				throw new IllegalArgumentException(filenameProduction + " is not available.");
			}
		}
	}

	protected final ApplicationContext newApplicatinContext(String... applicationContextLocator) {
		ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext(applicationContextLocator);
		return ac;
	}

	public TcmdbSpringTemplateFactory withWebserviceTemplateProvider(
			Class<? extends WebserviceTemplateProvider> templateProviderClass) {
	
		WebserviceTemplateFactory.setProviderClass(templateProviderClass);
		return this;
	}

	public TcmdbSpringTemplateFactory withConfigPropertiesAt(String location) {
		System.setProperty("de.servicezombie.tcmdb.configuration", location);
		return this;
	}

	public final SpringTemplate buildMongoTemplate() {

		SpringTemplate spring = buildByResourceLocation(
				toXmlFileNames(
						ConstantsForTest.SPRING_DEFAULT_PREFIX,
						ConstantsForTest.SPRING_MONGO_ONLY_FILES
					)
			);
		return spring;
	}

	public final SpringTemplate buildDefaultTemplate() {
		SpringTemplate spring = buildByXmlFilenames(
				ConstantsForTest.SPRING_DEFAULT_PREFIX, ConstantsForTest.SPRING_DEFAULT_FILES
				);
	
		return spring;
	}

	public final SpringTemplate buildByXmlFilenames(String prefix, String... names) {
		String[] files = toXmlFileNames(prefix, names);
		return buildByResourceLocation(files);
	}

}
